﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace iNotesNotification
{
    /// <summary>
    /// 
    /// </summary>
    public class ProcessController : IDisposable
    {
        private Thread _thread;
        private ParameterizedThreadStart _threadStart;
        private ProcessControllerContext _context;

        public ProcessController()
        {
            _threadStart = new ParameterizedThreadStart(Start);
            _context = new ProcessControllerContext("xml", "login", string.Empty);
        }

        public void Download(FileInfo file)
        {
            if (!IsRunning)
            {
                _thread = new Thread(_threadStart);

                _context.Interface = iNotesConfig.Instance.Interface;
                _context.Action = "download";
                _context.Data = file.FullName;
                _thread.Start(_context);
            }
        }

        public void Login()
        {
            if (!IsRunning)
            {
                _thread = new Thread(_threadStart);

                _context.Interface = iNotesConfig.Instance.Interface;
                _context.Action = "login";
                _thread.Start(_context);
            }
        }

        public bool WasSuccessfull
        {
            get
            {
                return (!IsRunning && _context.WasSuccessfull);
            }
        }

        public bool IsRunning
        {
            get
            {
                return ((_thread != null) && _thread.IsAlive);
            }
        }

        public void Abort()
        {
            if (this.IsRunning)
            {
                try
                {
                    _thread.Abort();
                    _thread.Join(100);
                    _thread = null;
                }
                catch { }
            }
        }

        public void Dispose()
        {
            Abort();
        }

        /// <summary>
        /// This will be running in a seperate thread. 
        /// </summary>
        /// <param name="o"></param>
        private static void Start(object o)
        {
            Process p = null;
            try
            {
                ProcessControllerContext context = o as ProcessControllerContext;
                if (context != null)
                {
                    StringBuilder arguments = new StringBuilder();
                    arguments.Append("-interface \"").Append(context.Interface);

                    if (context.Action == "login")
                    {
                        arguments.Append("\" -login");
                    }
                    else
                    {
                        arguments.Append("\" -saveas \"").Append(context.Data).Append("\"");
                    }

                    p = new Process();
                    ProcessStartInfo psi = new ProcessStartInfo(
                        iNotesController.AssemblyLocation.FullName,
                        arguments.ToString());
                    psi.CreateNoWindow = true;
                    psi.UseShellExecute = false;
                    psi.RedirectStandardOutput = true;
                    psi.WorkingDirectory = iNotesController.AssemblyLocation.Directory.FullName;
                    p.StartInfo = psi;

                    p.Start();
                    while (true)
                    {
                        string line = p.StandardOutput.ReadLine();
                        if (line != null)
                        {
                            if (line == bool.TrueString)
                            {
                                context.WasSuccessfull = (line == bool.TrueString);
                            }
                        }
                        else break;
                    }
                }
            }
            catch (ThreadAbortException)
            {
                if (p != null) { try { p.Kill(); } catch { } }
            }
            catch (Exception)
            {
                if (p != null) { try { p.Kill(); } catch { } }
            }
            p = null;
            return;
        }

        private class ProcessControllerContext
        {
            private bool _wasSuccessfull = false;
            private string _action;
            private string _data;
            private string _iface;

            public ProcessControllerContext(string iface, string action, string data)
            {
                _action = action;
                _data = data;
                _iface = iface;
            }

            public bool WasSuccessfull
            {
                get { return _wasSuccessfull; }
                set { _wasSuccessfull = value; }
            }

            public string Action
            {
                get { return _action; }
                set { _action = value; }
            }

            public string Data
            {
                get { return _data; }
                set { _data = value; }
            }

            public string Interface
            {
                get { return _iface; }
                set { _iface = value; }
            }
        }
    }
}
